package org.opengauss.evaluate.utils;

import lombok.extern.slf4j.Slf4j;
import org.opengauss.evaluate.common.exception.ServiceException;
import org.springframework.asm.ClassReader;
import org.springframework.asm.ClassVisitor;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author biao.yang
 * @Description: 评估工具类
 * @date 2025/3/14 11:16
 */
@Slf4j
public class EvaluateUtils {

    public static void main(String[] args) {
        try{
            Path startDir = Paths.get("E:\\Personal\\mumufei\\yiling\\yl-server-v2");
            Files.walk(startDir).filter(Files::isRegularFile)
                    .forEach(path -> {
                        String fileName = path.toString();
                        if (fileName.endsWith(".java")) {
                            processJavaFile(path);
                        } else if (fileName.endsWith(".xml")) {
                            //processXmlFile(path);
                        } else if (fileName.endsWith(".class")) {
                            processClassFile(path);
                        }
                    });
        }catch (Exception e) {
            log.error("Read path file fail.", e);
            throw new ServiceException("Read path file fail.");
        }

    }

    public static void processXmlFile(Path path) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(path.toFile());
            NodeList selectNodes = doc.getElementsByTagName("select");
            extractSqlFromNodes(selectNodes);
            // 类似处理insert、update、delete等标签
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void extractSqlFromNodes(NodeList nodes) {
        for (int i = 0; i < nodes.getLength(); i++) {
            Element element = (Element) nodes.item(i);
            String sql = element.getTextContent().trim();
            System.out.println("XML SQL: " + sql);
        }
    }

    public static void processJavaFile(Path path) {
        try {
            String content = Files.readString(path);
            // 匹配@Select、@Query等注解中的SQL
            Pattern annotationPattern = Pattern.compile("@Select\\(\"(.*?)\"\\)", Pattern.DOTALL);
            Matcher matcher = annotationPattern.matcher(content);
            while (matcher.find()) {
                System.out.println("Annotation SQL: " + matcher.group(1));
            }

            // 匹配字符串中的SQL（简易示例，实际需处理多行和拼接）
            Pattern stringPattern = Pattern.compile("\"((SELECT|INSERT|UPDATE|DELETE).*?)\"", Pattern.DOTALL);
            Matcher strMatcher = stringPattern.matcher(content);
            while (strMatcher.find()) {
                System.out.println("String SQL: " + strMatcher.group(1));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void processClassFile(Path path) {
        try {
            ClassReader reader = new ClassReader(Files.newInputStream(path));
            reader.accept(new ClassVisitor(Opcodes.ASM9) {
                @Override
                public MethodVisitor visitMethod(int access, String name, String descriptor,
                                                 String signature, String[] exceptions) {
                    return new MethodVisitor(Opcodes.ASM9) {
                        @Override
                        public void visitLdcInsn(Object value) {
                            if (value instanceof String) {
                                String str = (String) value;
                                if (looksLikeSql(str)) {
                                    System.out.println("Class SQL: " + str);
                                }
                            }
                        }
                    };
                }
            }, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static boolean looksLikeSql(String str) {
        return str.startsWith("SELECT") || str.startsWith("INSERT")
                || str.startsWith("UPDATE") || str.startsWith("DELETE");
    }
}
